package com.ruoyi.biz.service;

import com.ruoyi.biz.domain.BizProject;
import com.ruoyi.biz.enums.CostTypeEnum;
import com.ruoyi.biz.enums.ProjectStatusEnum;
import com.ruoyi.biz.mapper.BizCostMapper;
import com.ruoyi.biz.mapper.BizInvoiceMapper;
import com.ruoyi.biz.mapper.BizReceiptMapper;
import com.ruoyi.biz.model.req.StatReq;
import com.ruoyi.biz.model.resp.BizCostResp;
import com.ruoyi.biz.model.resp.BizInvoiceResp;
import com.ruoyi.biz.model.resp.stat.StatNVResp;
import com.ruoyi.biz.model.resp.stat.StatRiskResp;
import com.ruoyi.biz.utils.ReqUtils;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tianl
 * @date 2025/2/25
 * @description:
 */
@Service
public class StatRiskService {
    @Autowired
    private BizProjectService bizProjectService;
    @Autowired
    private BizInvoiceMapper bizInvoiceMapper;
    @Autowired
    private BizCostMapper bizCostMapper;

    public StatRiskResp statRiskBar(Integer year, Boolean all) {
        StatRiskResp statRiskResp = new StatRiskResp();
        List<BizProject> projectList = bizProjectService.listStat(new StatReq());
        if (CollectionUtils.isEmpty(projectList)) {
            return statRiskResp;
        }
        List<Long> projectIds = projectList.stream().map(BizProject::getId).collect(Collectors.toList());
        List<BizInvoiceResp> invoiceList = bizInvoiceMapper.listByProjectIds(projectIds);
        Map<String, List<BizInvoiceResp>> map = invoiceList.stream()
                .collect(Collectors.groupingBy(BizInvoiceResp::getInvoiceSubject));
        List<String> list = invoiceList.stream()
                .filter(item -> {
                    LocalDate itemDate = item.getInvoiceTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    return itemDate.getYear() == year; // 过滤出今年的数据
                })
                .collect(Collectors.groupingBy(
                        BizInvoiceResp::getInvoiceSubject, // 按name分组
                        Collectors.mapping(BizInvoiceResp::getInvoiceMoney, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)) // 对amount求和
                ))
                .entrySet().stream() // 转为流，以便进一步处理
                .sorted(Map.Entry.<String, BigDecimal>comparingByValue() // 按sum升序排序
                        .thenComparing(Map.Entry.comparingByKey())) // 若sum相同则按name升序排序
                .map(Map.Entry::getKey) // 提取name
                .collect(Collectors.toList()); // 收集结果为List<String>
        if (list.size() > 10 && !all) {
            list = list.stream().skip(Math.max(0, list.size() - 10)) // 确保不会跳过负数
                    .collect(Collectors.toList());
            ;
        }
        List<BigDecimal> num1List = new ArrayList<>();
        List<BigDecimal> num2List = new ArrayList<>();
        List<BigDecimal> num3List = new ArrayList<>();
        for (String name : list) {
            List<BizInvoiceResp> tmp = map.get(name);
            if (CollectionUtils.isEmpty(tmp)) {
                num1List.add(BigDecimal.ZERO);
                num2List.add(BigDecimal.ZERO);
                num3List.add(BigDecimal.ZERO);
                continue;
            }
            BigDecimal num1 = tmp.stream()
                    .filter(item -> {
                        LocalDate itemDate = item.getInvoiceTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        return itemDate.getYear() == year; // 过滤出今年的数据
                    }).map(BizInvoiceResp::getInvoiceMoney)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal num2 = tmp.stream()
                    .filter(item -> {
                        LocalDate itemDate = item.getInvoiceTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        return itemDate.getYear() == year - 1; // 过滤出今年的数据
                    }).map(BizInvoiceResp::getInvoiceMoney)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal num3 = tmp.stream()
                    .filter(item -> {
                        LocalDate itemDate = item.getInvoiceTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                        return itemDate.getYear() == year - 2; // 过滤出今年的数据
                    }).map(BizInvoiceResp::getInvoiceMoney)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            num1List.add(num1);
            num2List.add(num2);
            num3List.add(num3);
        }
        statRiskResp.setNameList(list);
        statRiskResp.setNum1List(num1List);
        statRiskResp.setNum2List(num2List);
        statRiskResp.setNum3List(num3List);
        return statRiskResp;
    }

    public List<StatNVResp> statCostBar(Integer year) {
        StatReq req = ReqUtils.getReq(year);
        List<StatNVResp> result = new ArrayList<>();
        List<BizProject> projectList = bizProjectService.listStat(req);
        if (CollectionUtils.isEmpty(projectList)) {
            return result;
        }
        List<Long> projectIds = projectList.stream().map(BizProject::getId).collect(Collectors.toList());
        List<BizCostResp> invoiceList = bizCostMapper.listByProjectIds(projectIds);
        Map<String, List<BizCostResp>> map = invoiceList.stream()
                .collect(Collectors.groupingBy(BizCostResp::getCostType));

        Map<String, String> nameMap = CostTypeEnum.toList().stream()
                .collect(Collectors.toMap(r -> r.getString("code"), i -> i.getString("name")));
        for (Map.Entry<String, List<BizCostResp>> entry : map.entrySet()) {
            StatNVResp tmp = new StatNVResp();
            tmp.setName(nameMap.get(entry.getKey()));
            tmp.setValue(entry.getValue().stream().map(BizCostResp::getCostMoney).reduce(BigDecimal.ZERO, BigDecimal::add));
            result.add(tmp);
        }
        return result;
    }

    public List<StatNVResp> riskWord() {
        List<BizProject> projectList = bizProjectService.listStat(new StatReq());
        List<StatNVResp> result = new ArrayList<>();
        projectList = projectList.stream()
                .filter(r -> r.getProjectStatus().equals(ProjectStatusEnum.CANCEL.getCode())
                        || r.getProjectStatus().equals(ProjectStatusEnum.OVERDUE.getCode())
                        || r.getProjectStatus().equals(ProjectStatusEnum.JUDICIAL.getCode()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(projectList)) {
            return result;
        }
        Map<String, Integer> resultMap = new HashMap<>();
        for (BizProject project : projectList) {
            if (project.getLocation() == null || project.getLocation().size() <= 0) {
                continue;
            }
            List<String> strs = project.getLocation().toStr();
            // 获取name列表并组合成字符串
            String combinedName = strs.get(strs.size() - 1);
            // 更新Map中的计数
            resultMap.put(combinedName, resultMap.getOrDefault(combinedName, 0) + 1);
        }
        for (Map.Entry<String, Integer> entry : resultMap.entrySet()) {
            StatNVResp resp = new StatNVResp();
            resp.setName(entry.getKey());
            resp.setValue(entry.getValue());
            result.add(resp);
        }
        return result;
    }
}
